<template>
  <div class="table_wrapper">
    <!-- 搜索 -->
    <div class="search_wrapper" v-if="getOptions.showSearch">
      <slot name="tableSearch"></slot>
    </div>
    <!-- 表格 -->
    <div class="a_base_table">
      <a-table
        :columns="iColumns"
        :data-source="dataSource"
        :row-key="getOptions.rowKey"
        :row-selection="getSelections"
        :loading="getOptions.loading"
        :bordered="getOptions.bordered"
        :scroll="getOptions.scroll"
        :pagination="false"
      >
        <!-- 自定义插槽 -->
        <template
          v-for="col in getOptions.$slotsName"
          #[col]="{ text, record, index }"
        >
          <slot :name="col" v-bind="{ text, record, index }"></slot>
        </template>
        <!--  -->

        <!-- 标签 -->
        <template #tags="{ text: tags }">
          <span>
            <a-tag v-for="tag in tags" :key="tag" :color="tagColors[tag.color]">
              {{ tag.name }}
            </a-tag>
          </span>
        </template>
        <!-- -->
      </a-table>
      <a-pagination
        v-if="getPagesOptions.show"
        v-model:current="pageNum"
        :disabled="getPagesOptions.disabled"
        :page-size-options="getPagesOptions.pageSizeOptions"
        :show-quick-jumper="getPagesOptions.showQuickJumper"
        :show-size-changer="getPagesOptions.showSizeChanger"
        :show-total="getPagesOptions.showTotal"
        :total="pageTotal"
        :page-size="pageSize"
        @showSizeChange="handleSizeChange"
        @change="handleCurrentChange"
      >
        <template #buildOptionText="props">
          <span>{{ props.value }}{{ $t("pages.optionText") }}</span>
        </template>
      </a-pagination>
    </div>
  </div>
</template>

<script lang="ts">
import {
  defineComponent,
  onMounted,
  computed,
  reactive,
  ref,
  unref,
  getCurrentInstance,
  Ref,
  onBeforeMount,
} from "vue";
import { useI18n } from "vue-i18n";
import { ColumnProps } from "ant-design-vue/es/table/interface";

type Key = ColumnProps["key"];

export default defineComponent({
  name: "ABaseTable",
  props: {
    /**
     * options: 配置
     * columns: 列
     * pagesOptions: 分页
     * api: 请求接口
     */
    options: {
      type: Object,
      default: () => {},
    },
    selections: {
      type: Object,
      default: () => {},
    },
    pagesOptions: {
      type: Object,
      default: () => {},
    },
    columns: {
      type: Array,
      required: true,
    },
    api: {
      type: Object,
      default: () => {},
      required: true,
    },
  },
  emits: ['handleSelectChange'],
  components: {},
  setup(props, { attrs, slots, emit }) {
    const { columns, options, selections, pagesOptions, api } = props;
    const { t } = useI18n();

    let pageSize = ref(10),
      pageNum = ref(1),
      pageTotal = ref(0);
    /**
     * 合并配置项
     */
    // 表格相关
    const getOptions = computed(() => {
      // Antd Table 所有配置项
      const defaultOptions = {
        showSearch: true,
        showIndex: true,
        bordered: false,
        loading: true,
        rowKey: "id",
        scroll: {},
        $slotsName: [], // 插槽名称，与columns.slots对应
      };
      return Object.assign(defaultOptions, options || {});
    });

    // 选择相关
    const selectedRowKeys = ref<Key[]>([]);
    if(selections.selectedRowKeys !== undefined) {
      selectedRowKeys.value = selections.selectedRowKeys;
      Reflect.deleteProperty(selections, 'selectedRowKeys')
    }
    const onSelectChange = (keys: Key[], rows: any[]) => { //, 
      emit('handleSelectChange', {keys, rows})
      selectedRowKeys.value = keys;
    };
    const getSelections = computed(() => {
      // Antd Table rowSelection 配置项
      const defaultOptions = {
        selectedRowKeys: unref(selectedRowKeys),
        onChange: onSelectChange
      };
      // 默认选中
      return Object.assign(defaultOptions, selections || {});
    });

    // 分页相关
    const getPagesOptions = computed(() => {
      // Antd Pagination 所有配置项
      const defaultOptions = {
        show: true,
        disabled: false,
        pageSizeOptions: ["10", "20", "50", "100"],
        showQuickJumper: true,
        showSizeChanger: true,
        showTotal: (total: number) => t("pages.total", { num: total }),
      };
      return Object.assign(defaultOptions, pagesOptions || {});
    });

    /** */

    /**
     * api 相关
     */
    let dataSource = ref([]);
    const handleGetData = async (): Promise<void> => {
      getOptions.value.loading = true;

      const params = Object.assign({}, api.params, {
        pageNum: pageNum.value,
        pageSize: pageSize.value,
      });
      // 请求数据
      const tableRes = await api.url(params);
      if (tableRes.data.status === "200") {
        const { data, total } = tableRes.data.data;
        dataSource.value = data;
        pageTotal.value = total;
      }
      getOptions.value.loading = false;
    };
    /** */

    onBeforeMount(async () => {
      handleGetData();
    });

    /**
     * 分页相关事件
     */
    // pageSize changed
    const handleCurrentChange = (page: number, pageSize: number): void => {
      pageNum.value = page;
      handleGetData();
    };

    // pageSize changed
    const handleSizeChange = (current: number, size: number): void => {
      pageSize.value = size;
      pageNum.value = 1;
      handleGetData();
    };

    /** */

    // 序号
    const iColumns = computed(() => {
      let indexCol = [
        {
          width: 80,
          customRender: ({ index }: { index: number }) => `${index + 1}`,
          title: "序号",
        },
      ];
      return getOptions.value.showIndex
        ? indexCol.concat(columns as any[])
        : columns;
    });

    // 标签颜色
    const tagColors = [
      "pink",
      "red",
      "orange",
      "green",
      "cyan",
      "blue",
      "purple",
    ];

    return {
      iColumns,
      getOptions,
      getSelections,
      getPagesOptions,
      dataSource,
      pageNum,
      pageSize,
      pageTotal,
      handleCurrentChange,
      handleSizeChange,
      tagColors,
      handleGetData,
    };
  },
});
</script>

<style lang="scss" scoped>
:deep(.search_wrapper) {
  .ant-col {
    margin-bottom: $gutter;
  }
  .ant-col-2 {
    flex: 0;
    width: auto;
  }
  .ant-col-4 {
    max-width: 270px;
    min-width: 200px;
  }
}
</style>